package xstring

import (
	"regexp"
	"strconv"
	"strings"
)

// 效验用户输入的规则符合用户名规则：英文大小写字母+数字
//
//	c	待效验的字符串
func CheckUsername(c string) bool {
	return regexp.MustCompile(`^[A-Za-z0-9]+$`).MatchString(c)
}

// 效验用户输入的规则是否符合密码规则
//
//	c	待效验的字符串
//	num	必须输入数字？
//	a	必须输入小写字母？
//	A	必须输入大写字母？
//	f	必须存在ANSI标识内的符号
func CheckPassword(c string, num, a, A, f bool) bool {
	if c == "" {
		return false
	}
	if num && !HasNumber(c) {
		return false
	}
	if a && !HasLetterLower(c) {
		return false
	}
	if A && !HasLetterUp(c) {
		return false
	}
	if f && !HasPunct(c) {
		return false
	}
	return true
}

// 手机号规则效验-国内手机号效验
//
//	c	待效验的手机号
//	fix	是否携带前缀
func CheckPhone(c string, fix bool) bool {
	if fix {
		return regexp.MustCompile(`^(\+?0?86\-?)?1[345789]\d{9}$`).MatchString(c)
	}
	return regexp.MustCompile(`^1[345789]\d{9}$`).MatchString(c)
}

// 手机号规则效验-国际手机号效验（携带前缀）
//
//	c	待效验的手机号
//	gj	国家标识[如果不存在的话就会返回false，支持列表为内部的gj_phone字典进行效验，空表示全部效验，只要有一个通过就行]
func CheckPhoneOther(c string, gj string) bool {
	var gj_phone map[string]string = map[string]string{
		"ar-DZ": `^(\+?213|0)(5|6|7)\d{8}$`,                                                                        // 阿尔及利亚
		"ar-SY": `^(!?(\+?963)|0)?9\d{8}$`,                                                                         // 叙利亚
		"ar-SA": `^(!?(\+?966)|0)?5\d{8}$`,                                                                         // 沙特阿拉伯
		"en-US": `^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$`,                                                             // 美国
		"cs-CZ": `^(\+?420)? ?[1-9][0-9]{2} ?[0-9]{3} ?[0-9]{3}$`,                                                  // 捷克
		"de-DE": `^(\+?49[ \.\-])?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$`, // 德国 -德国
		"da-DK": `^(\+?45)?(\d{8})$`,                                                                               // 丹麦文 -丹麦
		"el-GR": `^(\+?30)?(69\d{8})$`,                                                                             // 希腊 -希腊
		"en-AU": `^(\+?61|0)4\d{8}$`,                                                                               // 英国 -澳洲
		"en-GB": `^(\+?44|0)7\d{9}$`,                                                                               // 英国 - 英国
		"en-HK": `^(\+?852\-?)?[569]\d{3}\-?\d{4}$`,                                                                // 英语(香港)
		"en-IN": `^(\+?91|0)?[789]\d{9}$`,                                                                          // 英语(印度)
		"en-NZ": `^(\+?64|0)2\d{7,9}$`,                                                                             // 英国 - 新西兰
		"en-ZA": `^(\+?27|0)\d{9}$`,                                                                                // 英国 - 南非
		"en-ZM": `^(\+?26)?09[567]\d{7}$`,                                                                          // 别姆巴文(赞比亚)
		"es-ES": `^(\+?34)?(6\d{1}|7[1234])\d{7}$`,                                                                 // 西班牙 -西班牙
		"fi-FI": `^(\+?358|0)\s?(4(0|1|2|4|5)?|50)\s?(\d\s?){4,8}\d$`,                                              // 芬兰语(芬兰)
		"fr-FR": `^(\+?33|0)[67]\d{8}$`,                                                                            // 法语(法国)
		"he-IL": `^(\+972|0)([23489]|5[0248]|77)[1-9]\d{6}`,                                                        // 希伯来语(以色列)
		"hu-HU": `^(\+?36)(20|30|70)\d{7}$`,                                                                        // 匈牙利语(匈牙利)
		"it-IT": `^(\+?39)?\s?3\d{2} ?\d{6,7}$`,                                                                    // 意大利语(意大利)
		"ja-JP": `^(\+?81|0)\d{1,4}[ \-]?\d{1,4}[ \-]?\d{4}$`,                                                      // 日本 -日本
		"ms-MY": `^(\+?6?01){1}(([145]{1}(\-|\s)?\d{7,8})|([236789]{1}(\s|\-)?\d{7}))$`,                            // 马来 -马来西亚
		"nb-NO": `^(\+?47)?[49]\d{7}$`,                                                                             // 挪威 (Bokm?l) - 挪威
		"nl-BE": `^(\+?32|0)4?\d{8}$`,                                                                              // 荷兰语(比利时)
		"nn-NO": `^(\+?47)?[49]\d{7}$`,                                                                             // 挪威语(挪威)
		"pl-PL": `^(\+?48)? ?[5-8]\d ?\d{3} ?\d{2} ?\d{2}$`,                                                        // 波兰语(波兰)
		"pt-BR": `^(\+?55|0)\-?[1-9]{2}\-?[2-9]{1}\d{3,4}\-?\d{4}$`,                                                // 葡萄牙 -巴西
		"pt-PT": `^(\+?351)?9[1236]\d{7}$`,                                                                         // 葡萄牙 -葡萄牙
		"ru-RU": `^(\+?7|8)?9\d{9}$`,                                                                               // 俄国 -俄国
		"sr-RS": `^(\+3816|06)[- \d]{5,9}$`,                                                                        // 塞尔维亚
		"tr-TR": `^(\+?90|0)?5\d{9}$`,                                                                              // 土耳其语 -土耳其
		"vi-VN": `^(\+?84|0)?((1(2([0-9])|6([2-9])|88|99))|(9((?!5)[0-9])))([0-9]{7})$`,                            // 越南 -越南
		"zh-CN": `^(\+?0?86\-?)?1[345789]\d{9}$`,                                                                   // 简体中文(中国)
		"zh-TW": `^(\+?886\-?|0)?9\d{8}$`,                                                                          // 繁体中文(台湾地区)
	}
	if gj == "" {
		for _, v := range gj_phone {
			if regexp.MustCompile(v).MatchString(c) {
				return true
			}
		}
		return false
	}
	if v, ok := gj_phone[gj]; ok {
		return regexp.MustCompile(v).MatchString(c)
	}
	return false
}

// 邮箱格式效验
//
//	c	待效验的邮箱
func CheckEmail(c string) bool {
	return regexp.MustCompile(`^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$`).MatchString(c)
}

// 纯数字格式效验
//
//	c	待效验的数字
func CheckNumber(c string) bool {
	return regexp.MustCompile(`^[0-9]*$`).MatchString(c)
}

// 域名格式效验
//
//	c	待效验的字符串
func CheckDomain(c string) bool {
	return regexp.MustCompile(`^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?$`).MatchString(c)
}

// 域名格式效验
//
//	c	待效验的字符串
func CheckUrl(c string) bool {
	return regexp.MustCompile(`^[a-zA-z]+://[^\s]*$`).MatchString(c)
}

// 电话格式效验
//
//	c	待效验的字符串
func CheckTel(c string) bool {
	return regexp.MustCompile(`^(\d{3}-\d{7,8}|\d{4}-\d{7,8})(-\d+)?$`).MatchString(c)
}

// IPV4格式效验
//
//	c	待效验的字符串
func CheckIpv4(c string) bool {
	return regexp.MustCompile(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`).MatchString(c)
}

// IPV6格式效验
//
//	c	待效验的字符串
func CheckIpv6(c string) bool {
	return regexp.MustCompile(`^([\da-fA-F]{1,4}:){6}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^::([\da-fA-F]{1,4}:){0,4}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:):([\da-fA-F]{1,4}:){0,3}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){2}:([\da-fA-F]{1,4}:){0,2}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){3}:([\da-fA-F]{1,4}:){0,1}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){4}:((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$`).MatchString(c)
}

// 中国国民身份证号效验[15、18位身份证号码格式]
//
//	c	待效验的字符串
func CheckCardNo(c string) bool {
	if len(c) != 18 {
		return len(c) == 15 && CheckNumber(c)
	}
	nSum := 0
	weight := [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
	valid_value := [11]byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
	for i := 0; i < len(c)-1; i++ {
		n, _ := strconv.Atoi(string(c[i]))
		nSum += n * weight[i]
	}
	mod := nSum % 11
	return valid_value[mod] == c[17]
}

// 日期格式效验
//
//	c	待效验的字符串
func CheckDate(c string) bool {
	return regexp.MustCompile(`^(\d{4}|\d{2})-\d{1,2}-\d{1,2}$`).MatchString(c)
}

// 时间格式效验
//
//	c	待效验的字符串
func CheckTime(c string) bool {
	return regexp.MustCompile(`^\d{1,2}:\d{1,2}:\d{1,2}$`).MatchString(c)
}

// 日期时间格式效验
//
//	c	待效验的字符串
func CheckDateTime(c string) bool {
	return regexp.MustCompile(`^(\d{4}|\d{2})-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}$`).MatchString(c)
}

// 指定正则格式效验
//
//	c	待效验的字符串
//	rep	正则表达式
func CheckRep(c, rep string) bool {
	return regexp.MustCompile(rep).MatchString(c)
}

// 版本检测，返回是否需要更新
//
//	min	最小版本号
//	now	当前版本号
func CheckVersion(min, now string) bool {
	if min == "" {
		return false
	}
	// 检测版本字符串格式是否正确，不正确则直接返回false
	if !CheckRep(min, `^[v|V]?\d(\.\d){1,}$`) {
		return false
	}
	if !CheckRep(now, `^[v|V]?\d(\.\d){1,}$`) {
		return false
	}
	// 去除版本号前缀v/V
	min = strings.ReplaceAll(min, "v", "")
	min = strings.ReplaceAll(min, "V", "")
	now = strings.ReplaceAll(now, "v", "")
	now = strings.ReplaceAll(now, "V", "")
	now_list := strings.Split(now, ".")
	min_list := strings.Split(min, ".")
	for i := 0; i < len(min_list); i++ {
		if len(now_list) <= i {
			continue
		}
		if ToInt(min_list[i]) > ToInt(now_list[i]) {
			return true
		}
	}
	return false
}
